function deepClone (obj) {
  // 为null或者基本数据类型 --- 直接返回
  if (obj === null || typeof obj !== 'object') {
    return obj;
  } 

  // 正则表达式和日期的判断
  if (obj instanceof Date) {
    return new Date(obj);
  }

  if (obj instanceof RegExp) {
    return new RegExp(obj);
  }

  // 剩下的就是object和Array类型了
  let neWObj = Array.isArray(obj) ? [] : {};

  // 深度拷贝obj里面对象或者array的内容 --- for in 遍历可枚举对象：数组和普通对象  for of 遍历可迭代对象：不能遍历普通对象，可以遍历数组，字符串、map
  for (let key in obj) {
    neWObj[key] = deepClone(obj[key]);
  }
  return neWObj;

}

const original = { a: 1, b: { c: 2 } };
const copied = deepClone(original);
console.log(copied)
console.log(original === copied)


// 上面存在一个问题，循环拷贝，不能跳出来
// const obj = {
//   a: 1,
//   b: {
//     c: b,
//   }
// }
// 解决方法 ： 用map记录已经处理的对象
function deepCloneBettter (obj, map = new Map()) {
  // 为null或者基本数据类型 --- 直接返回
  if (obj === null || typeof obj !== 'object') {
    return obj;
  } 

  // 正则表达式和日期的判断
  if (obj instanceof Date) {
    return new Date(obj);
  }

  if (obj instanceof RegExp) {
    return new RegExp(obj);
  }

  // 是否处理过
  // 处理过
  if (map.has(obj)) {
    return map.get(obj);
  }

  // 没有处理过
  // 剩下的就是object和Array类型了
  let neWObj = Array.isArray(obj) ? [] : {};

  // 深度拷贝obj里面对象或者array的内容 --- for in 遍历可枚举对象：数组和普通对象  for of 遍历可迭代对象：不能遍历普通对象，可以遍历数组，字符串、map
  for (let key in obj) {
    // 这一步判断是因为for in遍历可能会将对象原型链上的属性拿下来，我们需要过滤一下
    if (obj.hasOwnProperty(key)) {
      neWObj[key] = deepClone(obj[key]);
    }
  }
  map.set(obj, neWObj);
  return neWObj;

}

const copied1 = deepCloneBettter(original);
console.log(copied1)
console.log(original === copied1)